/**
 * 缓存管理工具
 */

/**
 * 缓存项接口
 */
interface CacheItem<T = any> {
  value: T;
  expire?: number;
  timestamp: number;
  accessCount: number;
  lastAccess: number;
}

/**
 * 缓存选项
 */
interface CacheOptions {
  maxSize?: number;
  defaultExpire?: number;
  enableLRU?: boolean;
  enableStats?: boolean;
}

/**
 * 缓存统计信息
 */
interface CacheStats {
  hits: number;
  misses: number;
  size: number;
  maxSize: number;
  hitRate: number;
}

/**
 * 内存缓存管理器
 */
export class MemoryCache {
  private cache = new Map<string, CacheItem>();
  private options: Required<CacheOptions>;
  private stats = {
    hits: 0,
    misses: 0
  };

  constructor(options: CacheOptions = {}) {
    this.options = {
      maxSize: 1000,
      defaultExpire: 0, // 0表示永不过期
      enableLRU: true,
      enableStats: true,
      ...options
    };
  }

  /**
   * 设置缓存
   */
  set<T>(key: string, value: T, expire?: number): void {
    const now = Date.now();
    const expireTime = expire || this.options.defaultExpire;
    
    // 如果启用LRU且缓存已满，删除最少使用的项
    if (this.options.enableLRU && this.cache.size >= this.options.maxSize) {
      this.evictLRU();
    }

    this.cache.set(key, {
      value,
      expire: expireTime > 0 ? now + expireTime : undefined,
      timestamp: now,
      accessCount: 0,
      lastAccess: now
    });
  }

  /**
   * 获取缓存
   */
  get<T>(key: string): T | null {
    const item = this.cache.get(key);
    
    if (!item) {
      if (this.options.enableStats) {
        this.stats.misses++;
      }
      return null;
    }

    const now = Date.now();

    // 检查是否过期
    if (item.expire && now > item.expire) {
      this.cache.delete(key);
      if (this.options.enableStats) {
        this.stats.misses++;
      }
      return null;
    }

    // 更新访问统计
    item.accessCount++;
    item.lastAccess = now;

    if (this.options.enableStats) {
      this.stats.hits++;
    }

    return item.value as T;
  }

  /**
   * 删除缓存
   */
  delete(key: string): boolean {
    return this.cache.delete(key);
  }

  /**
   * 检查是否存在
   */
  has(key: string): boolean {
    const item = this.cache.get(key);
    if (!item) return false;

    // 检查是否过期
    if (item.expire && Date.now() > item.expire) {
      this.cache.delete(key);
      return false;
    }

    return true;
  }

  /**
   * 清空缓存
   */
  clear(): void {
    this.cache.clear();
    this.stats.hits = 0;
    this.stats.misses = 0;
  }

  /**
   * 获取所有键
   */
  keys(): string[] {
    return Array.from(this.cache.keys());
  }

  /**
   * 获取缓存大小
   */
  size(): number {
    return this.cache.size;
  }

  /**
   * 获取统计信息
   */
  getStats(): CacheStats {
    const total = this.stats.hits + this.stats.misses;
    return {
      hits: this.stats.hits,
      misses: this.stats.misses,
      size: this.cache.size,
      maxSize: this.options.maxSize,
      hitRate: total > 0 ? this.stats.hits / total : 0
    };
  }

  /**
   * 清理过期项
   */
  cleanup(): number {
    const now = Date.now();
    let cleanedCount = 0;

    for (const [key, item] of this.cache.entries()) {
      if (item.expire && now > item.expire) {
        this.cache.delete(key);
        cleanedCount++;
      }
    }

    return cleanedCount;
  }

  /**
   * LRU淘汰策略
   */
  private evictLRU(): void {
    let oldestKey = '';
    let oldestTime = Date.now();

    for (const [key, item] of this.cache.entries()) {
      if (item.lastAccess < oldestTime) {
        oldestTime = item.lastAccess;
        oldestKey = key;
      }
    }

    if (oldestKey) {
      this.cache.delete(oldestKey);
    }
  }
}

/**
 * 本地存储缓存管理器
 */
export class LocalStorageCache {
  private prefix: string;
  private options: Required<CacheOptions>;

  constructor(prefix: string = 'cache_', options: CacheOptions = {}) {
    this.prefix = prefix;
    this.options = {
      maxSize: 1000,
      defaultExpire: 0,
      enableLRU: true,
      enableStats: true,
      ...options
    };
  }

  /**
   * 设置缓存
   */
  set<T>(key: string, value: T, expire?: number): void {
    try {
      const now = Date.now();
      const expireTime = expire || this.options.defaultExpire;
      
      const item: CacheItem<T> = {
        value,
        expire: expireTime > 0 ? now + expireTime : undefined,
        timestamp: now,
        accessCount: 0,
        lastAccess: now
      };

      localStorage.setItem(this.prefix + key, JSON.stringify(item));
    } catch (error) {
      console.error('设置本地存储缓存失败:', error);
    }
  }

  /**
   * 获取缓存
   */
  get<T>(key: string): T | null {
    try {
      const itemStr = localStorage.getItem(this.prefix + key);
      if (!itemStr) return null;

      const item: CacheItem<T> = JSON.parse(itemStr);
      const now = Date.now();

      // 检查是否过期
      if (item.expire && now > item.expire) {
        localStorage.removeItem(this.prefix + key);
        return null;
      }

      // 更新访问统计
      item.accessCount++;
      item.lastAccess = now;
      localStorage.setItem(this.prefix + key, JSON.stringify(item));

      return item.value;
    } catch (error) {
      console.error('获取本地存储缓存失败:', error);
      return null;
    }
  }

  /**
   * 删除缓存
   */
  delete(key: string): boolean {
    try {
      localStorage.removeItem(this.prefix + key);
      return true;
    } catch (error) {
      console.error('删除本地存储缓存失败:', error);
      return false;
    }
  }

  /**
   * 检查是否存在
   */
  has(key: string): boolean {
    try {
      const itemStr = localStorage.getItem(this.prefix + key);
      if (!itemStr) return false;

      const item: CacheItem = JSON.parse(itemStr);
      
      // 检查是否过期
      if (item.expire && Date.now() > item.expire) {
        localStorage.removeItem(this.prefix + key);
        return false;
      }

      return true;
    } catch (error) {
      console.error('检查本地存储缓存失败:', error);
      return false;
    }
  }

  /**
   * 清空缓存
   */
  clear(): void {
    try {
      const keys = Object.keys(localStorage);
      keys.forEach(key => {
        if (key.startsWith(this.prefix)) {
          localStorage.removeItem(key);
        }
      });
    } catch (error) {
      console.error('清空本地存储缓存失败:', error);
    }
  }

  /**
   * 获取所有键
   */
  keys(): string[] {
    try {
      const keys = Object.keys(localStorage);
      return keys
        .filter(key => key.startsWith(this.prefix))
        .map(key => key.substring(this.prefix.length));
    } catch (error) {
      console.error('获取本地存储缓存键失败:', error);
      return [];
    }
  }

  /**
   * 获取缓存大小
   */
  size(): number {
    return this.keys().length;
  }

  /**
   * 清理过期项
   */
  cleanup(): number {
    let cleanedCount = 0;
    const keys = this.keys();

    keys.forEach(key => {
      if (!this.has(key)) {
        cleanedCount++;
      }
    });

    return cleanedCount;
  }
}

/**
 * 会话存储缓存管理器
 */
export class SessionStorageCache {
  private prefix: string;
  private options: Required<CacheOptions>;

  constructor(prefix: string = 'session_cache_', options: CacheOptions = {}) {
    this.prefix = prefix;
    this.options = {
      maxSize: 1000,
      defaultExpire: 0,
      enableLRU: true,
      enableStats: true,
      ...options
    };
  }

  /**
   * 设置缓存
   */
  set<T>(key: string, value: T, expire?: number): void {
    try {
      const now = Date.now();
      const expireTime = expire || this.options.defaultExpire;
      
      const item: CacheItem<T> = {
        value,
        expire: expireTime > 0 ? now + expireTime : undefined,
        timestamp: now,
        accessCount: 0,
        lastAccess: now
      };

      sessionStorage.setItem(this.prefix + key, JSON.stringify(item));
    } catch (error) {
      console.error('设置会话存储缓存失败:', error);
    }
  }

  /**
   * 获取缓存
   */
  get<T>(key: string): T | null {
    try {
      const itemStr = sessionStorage.getItem(this.prefix + key);
      if (!itemStr) return null;

      const item: CacheItem<T> = JSON.parse(itemStr);
      const now = Date.now();

      // 检查是否过期
      if (item.expire && now > item.expire) {
        sessionStorage.removeItem(this.prefix + key);
        return null;
      }

      // 更新访问统计
      item.accessCount++;
      item.lastAccess = now;
      sessionStorage.setItem(this.prefix + key, JSON.stringify(item));

      return item.value;
    } catch (error) {
      console.error('获取会话存储缓存失败:', error);
      return null;
    }
  }

  /**
   * 删除缓存
   */
  delete(key: string): boolean {
    try {
      sessionStorage.removeItem(this.prefix + key);
      return true;
    } catch (error) {
      console.error('删除会话存储缓存失败:', error);
      return false;
    }
  }

  /**
   * 检查是否存在
   */
  has(key: string): boolean {
    try {
      const itemStr = sessionStorage.getItem(this.prefix + key);
      if (!itemStr) return false;

      const item: CacheItem = JSON.parse(itemStr);
      
      // 检查是否过期
      if (item.expire && Date.now() > item.expire) {
        sessionStorage.removeItem(this.prefix + key);
        return false;
      }

      return true;
    } catch (error) {
      console.error('检查会话存储缓存失败:', error);
      return false;
    }
  }

  /**
   * 清空缓存
   */
  clear(): void {
    try {
      const keys = Object.keys(sessionStorage);
      keys.forEach(key => {
        if (key.startsWith(this.prefix)) {
          sessionStorage.removeItem(key);
        }
      });
    } catch (error) {
      console.error('清空会话存储缓存失败:', error);
    }
  }

  /**
   * 获取所有键
   */
  keys(): string[] {
    try {
      const keys = Object.keys(sessionStorage);
      return keys
        .filter(key => key.startsWith(this.prefix))
        .map(key => key.substring(this.prefix.length));
    } catch (error) {
      console.error('获取会话存储缓存键失败:', error);
      return [];
    }
  }

  /**
   * 获取缓存大小
   */
  size(): number {
    return this.keys().length;
  }

  /**
   * 清理过期项
   */
  cleanup(): number {
    let cleanedCount = 0;
    const keys = this.keys();

    keys.forEach(key => {
      if (!this.has(key)) {
        cleanedCount++;
      }
    });

    return cleanedCount;
  }
}

/**
 * 统一缓存管理器
 */
export class CacheManager {
  private memoryCache: MemoryCache;
  private localStorageCache: LocalStorageCache;
  private sessionStorageCache: SessionStorageCache;

  constructor(options: CacheOptions = {}) {
    this.memoryCache = new MemoryCache(options);
    this.localStorageCache = new LocalStorageCache('cache_', options);
    this.sessionStorageCache = new SessionStorageCache('session_cache_', options);
  }

  /**
   * 设置内存缓存
   */
  setMemory<T>(key: string, value: T, expire?: number): void {
    this.memoryCache.set(key, value, expire);
  }

  /**
   * 获取内存缓存
   */
  getMemory<T>(key: string): T | null {
    return this.memoryCache.get<T>(key);
  }

  /**
   * 设置本地存储缓存
   */
  setLocal<T>(key: string, value: T, expire?: number): void {
    this.localStorageCache.set(key, value, expire);
  }

  /**
   * 获取本地存储缓存
   */
  getLocal<T>(key: string): T | null {
    return this.localStorageCache.get<T>(key);
  }

  /**
   * 设置会话存储缓存
   */
  setSession<T>(key: string, value: T, expire?: number): void {
    this.sessionStorageCache.set(key, value, expire);
  }

  /**
   * 获取会话存储缓存
   */
  getSession<T>(key: string): T | null {
    return this.sessionStorageCache.get<T>(key);
  }

  /**
   * 智能缓存：优先内存，其次本地存储
   */
  set<T>(key: string, value: T, expire?: number): void {
    this.memoryCache.set(key, value, expire);
    this.localStorageCache.set(key, value, expire);
  }

  /**
   * 智能获取：优先内存，其次本地存储
   */
  get<T>(key: string): T | null {
    let value = this.memoryCache.get<T>(key);
    if (value !== null) return value;

    value = this.localStorageCache.get<T>(key);
    if (value !== null) {
      // 同步到内存缓存
      this.memoryCache.set(key, value);
      return value;
    }

    return null;
  }

  /**
   * 删除缓存
   */
  delete(key: string): void {
    this.memoryCache.delete(key);
    this.localStorageCache.delete(key);
    this.sessionStorageCache.delete(key);
  }

  /**
   * 清空所有缓存
   */
  clear(): void {
    this.memoryCache.clear();
    this.localStorageCache.clear();
    this.sessionStorageCache.clear();
  }

  /**
   * 清理过期项
   */
  cleanup(): number {
    return this.memoryCache.cleanup() + 
           this.localStorageCache.cleanup() + 
           this.sessionStorageCache.cleanup();
  }

  /**
   * 获取统计信息
   */
  getStats() {
    return {
      memory: this.memoryCache.getStats(),
      local: this.localStorageCache.size(),
      session: this.sessionStorageCache.size()
    };
  }
}

/**
 * 全局缓存管理器实例
 */
export const cacheManager = new CacheManager();

/**
 * 缓存工具函数
 */
export const cacheUtils = {
  /**
   * 设置缓存
   */
  set: <T>(key: string, value: T, expire?: number) => cacheManager.set(key, value, expire),

  /**
   * 获取缓存
   */
  get: <T>(key: string) => cacheManager.get<T>(key),

  /**
   * 删除缓存
   */
  delete: (key: string) => cacheManager.delete(key),

  /**
   * 清空缓存
   */
  clear: () => cacheManager.clear(),

  /**
   * 清理过期项
   */
  cleanup: () => cacheManager.cleanup(),

  /**
   * 获取统计信息
   */
  getStats: () => cacheManager.getStats(),

  /**
   * 创建内存缓存
   */
  createMemory: (options?: CacheOptions) => new MemoryCache(options),

  /**
   * 创建本地存储缓存
   */
  createLocal: (prefix?: string, options?: CacheOptions) => new LocalStorageCache(prefix, options),

  /**
   * 创建会话存储缓存
   */
  createSession: (prefix?: string, options?: CacheOptions) => new SessionStorageCache(prefix, options)
};
